//
//  DebugNSURLProtocol.m
//  YK_DebugManager
//
//  Created by edward on 2021/1/15.
//

#import "DebugNSURLProtocol.h"
#import "DebugNetWorkManager.h"
#import "DebugNetWorkSaveUtil.h"


static NSString * const kDebugManagerProtocolKey = @"debugmanager_protocol_key";

@interface DebugNSURLProtocol ()<NSURLSessionDataDelegate>

@property(nonatomic,strong) NSURLSession *session;
///
@property(nonatomic,strong) NSURLSessionDataTask *task;

@property (nonatomic, strong) NSURLSession *urlSession;
@property (nonatomic, strong) NSDate *startTime;
@property (nonatomic, strong) NSURLResponse *response;
@property (nonatomic, strong) NSMutableData *data;
@property (nonatomic, strong) NSError *error;

@property (atomic, strong, readwrite) NSThread *clientThread;
@property (atomic, copy,   readwrite) NSArray *modes;
@end

@implementation DebugNSURLProtocol

+ (BOOL)canInitWithTask:(NSURLSessionTask *)task {
    NSURLRequest *request = task.currentRequest;
    return request == nil ? NO : [self canInitWithRequest:request];
}

+ (BOOL)canInitWithRequest:(NSURLRequest *)request{
    if ([NSURLProtocol propertyForKey:kDebugManagerProtocolKey inRequest:request]) {
        return NO;
    }
    //
//    if (!) {
//        return NO;
//    }
    if (![request.URL.scheme isEqualToString:@"http"] &&
        ![request.URL.scheme isEqualToString:@"https"]) {
        return NO;
    }
    //文件类型不作处理
    NSString *contentType = [request valueForHTTPHeaderField:@"Content-Type"];
    if (contentType && [contentType containsString:@"multipart/form-data"]) {
        return NO;
    }
    return [DebugNetWorkManager sharedInstance].isRecordNetWorking;
}
+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request{
    NSMutableURLRequest *mutableReqeust = [request mutableCopy];
    [NSURLProtocol setProperty:@YES forKey:kDebugManagerProtocolKey inRequest:mutableReqeust];
    return [mutableReqeust copy];
}
- (void)startLoading
{
    NSMutableURLRequest *   recursiveRequest;
    NSMutableArray *        calculatedModes;
    NSString *              currentMode;
    
    
    calculatedModes = [NSMutableArray array];
    [calculatedModes addObject:NSDefaultRunLoopMode];
    currentMode = [[NSRunLoop currentRunLoop] currentMode];
    if ( (currentMode != nil) && ! [currentMode isEqual:NSDefaultRunLoopMode] ) {
        [calculatedModes addObject:currentMode];
    }
    self.modes = calculatedModes;
    self.clientThread = [NSThread currentThread];
    self.data = [NSMutableData data];
    self.startTime = [NSDate date];
    recursiveRequest = [[self request] mutableCopy];
    assert(recursiveRequest != nil);
    self.task = [self.session dataTaskWithRequest:recursiveRequest];
    assert(self.task != nil);
    [self.task resume];
}
- (void)stopLoading
{
    [[DebugNetWorkSaveUtil sharedInstance] save:self.request response:self.response startTime:self.startTime data:self.data];
    if (self.task != nil) {
        [self.task cancel];
        self.task = nil;
    }
}
#pragma mark - NSURLSessionDelegate

- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler
{
    self.response = response;
    [self.client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed];
    completionHandler(NSURLSessionResponseAllow);
    
}
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
{
    [self.data appendData:data];
    [self.client URLProtocol:self didLoadData:data];
}

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
    if (error) {
        self.error = error;
        [self.client URLProtocol:self didFailWithError:error];
    }else{
        [self.client URLProtocolDidFinishLoading:self];
    }
}

- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler
{
    //判断服务器返回的证书类型, 是否是服务器信任
    if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
        //强制信任
        NSURLCredential *card = [[NSURLCredential alloc]initWithTrust:challenge.protectionSpace.serverTrust];
        completionHandler(NSURLSessionAuthChallengeUseCredential, card);
    }
}




#pragma mark -- getter/setter
- (NSURLSession *)session
{
    if (!_session) {
        NSOperationQueue *queue =[[NSOperationQueue alloc] init];
        
        [queue setMaxConcurrentOperationCount:1];
        [queue setName:@"DebugNSURLProtocol"];
        _session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:queue];
        _session.sessionDescription = @"DebugNSURLProtocol";
    }
    return _session;
}
@end
